// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0

import { ComboBox } from "std-widgets.slint";
export component TestCase inherits Window {
    width: 200px;
    height: 200px;

    in-out property <string> output;
    TouchArea {
        clicked => { output += "clicked-under\n"; }
    }

    VerticalLayout {
        alignment: center;
        box := ComboBox {
            model: ["Aaa", "Bbb", "Ccc"];
            selected => {
                output += "selected("+self.current-value+","+self.current-index+")\n";
            }
        }
    }

    public function unfocus() {
        box.clear-focus();
    }

    in-out property current-index <=> box.current-index;
    in-out property current-value <=> box.current-value;
    in-out property model <=> box.model;
    out property has-focus <=> box.has-focus;
}

/*


```rust
use std::rc::Rc;
use slint::{platform::WindowEvent, platform::Key, VecModel, SharedString, LogicalPosition};
use i_slint_backend_testing::mock_elapsed_time;

let instance = TestCase::new().unwrap();

assert_eq!(instance.get_current_value(), "Aaa");
assert_eq!(instance.get_current_index(), 0);
assert_eq!(instance.get_has_focus(), false);

let mut combobox_search = slint_testing::ElementHandle::find_by_element_id(&instance, "TestCase::box");
let combobox = combobox_search.next().unwrap();
assert_eq!(combobox.accessible_expandable(), Some(true));
assert_eq!(combobox.accessible_expanded(), Some(false));
assert_eq!(combobox.accessible_value(), Some(SharedString::from("Aaa")));

// Change the index programmatically
instance.set_current_index(1);
assert_eq!(instance.get_current_value(), "Bbb");
assert_eq!(instance.get_current_index(), 1);
assert_eq!(combobox.accessible_value(), Some(SharedString::from("Bbb")));
assert_eq!(instance.get_output(), "");
instance.set_current_index(0);
assert_eq!(instance.get_current_value(), "Aaa");
assert_eq!(instance.get_current_index(), 0);
assert_eq!(combobox.accessible_value(), Some(SharedString::from("Aaa")));
assert_eq!(instance.get_output(), "");
assert_eq!(instance.get_has_focus(), false);

// Open the combobox
slint_testing::send_mouse_click(&instance, 100., 100.);
assert_eq!(instance.get_output(), "");
assert_eq!(instance.get_has_focus(), true);
assert_eq!(combobox.accessible_expanded(), Some(true));

// click outside of the combobox, this should close it
slint_testing::send_mouse_click(&instance, 100., 10.);
assert_eq!(instance.get_output(), "");
assert_eq!(instance.get_current_value(), "Aaa");
assert_eq!(instance.get_current_index(), 0);
assert_eq!(combobox.accessible_value(), Some(SharedString::from("Aaa")));
assert_eq!(instance.get_has_focus(), true);
assert_eq!(combobox.accessible_expanded(), Some(false));

// click outside of the combobox again
slint_testing::send_mouse_click(&instance, 100., 10.);
assert_eq!(instance.get_output(), "clicked-under\n");
instance.set_output(Default::default());
assert_eq!(instance.get_current_value(), "Aaa");
assert_eq!(instance.get_current_index(), 0);
assert_eq!(combobox.accessible_value(), Some(SharedString::from("Aaa")));
assert_eq!(instance.get_has_focus(), true);
assert_eq!(combobox.accessible_expanded(), Some(false));


// The arrow change the values
slint_testing::send_keyboard_string_sequence(&instance, &SharedString::from(Key::DownArrow));
assert_eq!(instance.get_current_value(), "Bbb");
assert_eq!(instance.get_current_index(), 1);
assert_eq!(combobox.accessible_value(), Some(SharedString::from("Bbb")));
assert_eq!(instance.get_output(), "selected(Bbb,1)\n");
slint_testing::send_keyboard_string_sequence(&instance, &SharedString::from(Key::DownArrow));
assert_eq!(instance.get_current_value(), "Ccc");
assert_eq!(instance.get_current_index(), 2);
assert_eq!(combobox.accessible_value(), Some(SharedString::from("Ccc")));
assert_eq!(instance.get_output(), "selected(Bbb,1)\nselected(Ccc,2)\n");
slint_testing::send_keyboard_string_sequence(&instance, &SharedString::from(Key::UpArrow));
assert_eq!(instance.get_current_value(), "Bbb");
assert_eq!(instance.get_current_index(), 1);
assert_eq!(combobox.accessible_value(), Some(SharedString::from("Bbb")));
assert_eq!(instance.get_output(), "selected(Bbb,1)\nselected(Ccc,2)\nselected(Bbb,1)\n");
instance.set_output(Default::default());

// show the popup
slint_testing::send_keyboard_string_sequence(&instance, &SharedString::from(Key::Return));
assert_eq!(instance.get_output(), "");
assert_eq!(combobox.accessible_expanded(), Some(true));
// click outside causes the popup to close
slint_testing::send_mouse_click(&instance, 100., 10.);
assert_eq!(instance.get_output(), "");
assert_eq!(instance.get_has_focus(), true);
assert_eq!(combobox.accessible_expanded(), Some(false));
slint_testing::send_mouse_click(&instance, 100., 10.);
assert_eq!(instance.get_output(), "clicked-under\n");
assert_eq!(instance.get_has_focus(), true);
assert_eq!(combobox.accessible_expanded(), Some(false));
instance.set_output(Default::default());

instance.set_current_index(0);


// show the popup
slint_testing::send_keyboard_string_sequence(&instance, &SharedString::from(Key::Return));
// The arrow change the values while the popup is shown
slint_testing::send_keyboard_string_sequence(&instance, &SharedString::from(Key::DownArrow));
assert_eq!(instance.get_current_value(), "Bbb");
assert_eq!(instance.get_current_index(), 1);
assert_eq!(combobox.accessible_value(), Some(SharedString::from("Bbb")));
assert_eq!(instance.get_output(), "selected(Bbb,1)\n");
slint_testing::send_keyboard_string_sequence(&instance, &SharedString::from(Key::DownArrow));
assert_eq!(instance.get_current_value(), "Ccc");
assert_eq!(instance.get_current_index(), 2);
assert_eq!(combobox.accessible_value(), Some(SharedString::from("Ccc")));
assert_eq!(instance.get_output(), "selected(Bbb,1)\nselected(Ccc,2)\n");
slint_testing::send_keyboard_string_sequence(&instance, &SharedString::from(Key::UpArrow));
assert_eq!(instance.get_current_value(), "Bbb");
assert_eq!(instance.get_current_index(), 1);
assert_eq!(combobox.accessible_value(), Some(SharedString::from("Bbb")));
assert_eq!(instance.get_output(), "selected(Bbb,1)\nselected(Ccc,2)\nselected(Bbb,1)\n");
// close the popup
slint_testing::send_keyboard_string_sequence(&instance, &SharedString::from(Key::Escape));
assert_eq!(instance.get_current_value(), "Bbb");
assert_eq!(instance.get_current_index(), 1);
assert_eq!(combobox.accessible_value(), Some(SharedString::from("Bbb")));
assert_eq!(instance.get_output(), "selected(Bbb,1)\nselected(Ccc,2)\nselected(Bbb,1)\n");
instance.set_output(Default::default());
slint_testing::send_mouse_click(&instance, 100., 10.);
assert_eq!(instance.get_output(), "clicked-under\n");
assert_eq!(combobox.accessible_expanded(), Some(false));
assert_eq!(instance.get_has_focus(), true);
instance.set_output(Default::default());


// The accessible expand action should open the popup
combobox.invoke_accessible_expand_action();
assert_eq!(instance.get_output(), "");
assert_eq!(instance.get_has_focus(), true);
assert_eq!(combobox.accessible_expanded(), Some(true));
// close the popup
slint_testing::send_keyboard_string_sequence(&instance, &SharedString::from(Key::Escape));
assert_eq!(instance.get_output(), "");
assert_eq!(instance.get_has_focus(), true);
assert_eq!(combobox.accessible_expanded(), Some(false));

// Scroll with the wheel
let wheel_change_value = !module_path!().contains("cupertino");
instance.set_output(Default::default());
instance.window().dispatch_event(WindowEvent::PointerScrolled { position: LogicalPosition::new(100.0, 100.0), delta_x: 0.0, delta_y: 20.0 });
if wheel_change_value {
    assert_eq!(instance.get_current_value(), "Aaa");
    assert_eq!(instance.get_current_index(), 0);
    assert_eq!(instance.get_output(), "selected(Aaa,0)\n");
} else {
    assert_eq!(instance.get_current_value(), "Bbb");
    assert_eq!(instance.get_current_index(), 1);
    assert_eq!(instance.get_output(), "");
}
instance.window().dispatch_event(WindowEvent::PointerScrolled { position: LogicalPosition::new(100.0, 100.0), delta_x: 0.0, delta_y: -5.0 });
assert_eq!(instance.get_has_focus(), true);
assert_eq!(instance.get_current_value(), "Bbb");
assert_eq!(instance.get_current_index(), 1);
if wheel_change_value {
    assert_eq!(instance.get_output(), "selected(Aaa,0)\nselected(Bbb,1)\n");
}
// When not having focus, do nothing
instance.invoke_unfocus();
instance.set_output(Default::default());
assert_eq!(instance.get_has_focus(), false);
instance.window().dispatch_event(WindowEvent::PointerScrolled { position: LogicalPosition::new(100.0, 100.0), delta_x: 0.0, delta_y: 20.0 });
assert_eq!(instance.get_current_value(), "Bbb");
assert_eq!(instance.get_current_index(), 1);
instance.window().dispatch_event(WindowEvent::PointerScrolled { position: LogicalPosition::new(100.0, 100.0), delta_x: 0.0, delta_y: -5.0 });
assert_eq!(instance.get_has_focus(), false);
assert_eq!(instance.get_current_value(), "Bbb");
assert_eq!(instance.get_current_index(), 1);
assert_eq!(instance.get_output(), "");
slint_testing::send_keyboard_string_sequence(&instance, "\t");
assert_eq!(instance.get_has_focus(), true);

// Set current-index to -1
instance.set_current_index(-1);
mock_elapsed_time(500);
assert_eq!(instance.get_current_value(), &SharedString::from(""));
assert_eq!(combobox.accessible_value(), Some(SharedString::from("")));

// Replace model
instance.set_model(Rc::new(VecModel::from_slice(&[SharedString::from("A"), SharedString::from("B")])).into());
mock_elapsed_time(500);
assert_eq!(instance.get_current_index(), 0);
assert_eq!(instance.get_current_value(), &SharedString::from("A"));
assert_eq!(combobox.accessible_value(), Some(SharedString::from("A")));
```

*/
